///////////////////////////////////////////////////////////////////////////////
//	FILENAME:	8Bawl.m
//	SUMMARY:	an Eight-Ball (TM) Annotation
//	SUPERCLASS:	Object
//	INTERFACE:	None
//	PROTOCOLS:	<Annotation, Tool>
//	AUTHOR:		Eric P. Scott, ported to eText by Rohit Khare
//	COPYRIGHT:	(c) 1994 California Institure of Technology, eText Project
//	COPYRIGHT:	(c) 1994 San Francisco State University
///////////////////////////////////////////////////////////////////////////////
//	DESCRIPTION
//		An example of how to port over a simple View-based widget. Original
//	application and 8Bawl source code by Eric P. Scott, Tech alum @ SFSU
///////////////////////////////////////////////////////////////////////////////
// 			BawlApp.m: a toy for the virtual desktop
// 			Eric P. Scott, San Francisco State University, January 1994
///////////////////////////////////////////////////////////////////////////////
//	HISTORY
//	05/22/94:	Created. First eText port.
///////////////////////////////////////////////////////////////////////////////

#import "eTextKernel.h"
#include "wraps8.h"
#include <bsd/libc.h>

#define	NIMAGES 21
@class EBI;

// File-Scope Global shared by all 8Bawls
id	face[NIMAGES];
id	base8;
id	big8;
BOOL initted=NO;


@interface EightBawl:Object <Annotation, Tool>
{	BOOL	highlighted;
	int		animStep;
	id		cimage;
	NXRect  savedFrame;
	NXPoint savedPoint;
}
@end

@implementation EightBawl

const NXRect bigRect={ { 0.0, 0.0 }, { 288.0, 288.0 } };
const NXPoint smallRectOrigin={ 96.0, 88.0}, smallRectUpOrigin={ 96.0, 116.0};
const NXSize smallRectSize={ 96.0, 84.0};

+ toolAwake:theApp
{
    long 		now;
	int 		i;
	char        buf[MAXPATHLEN];
	NXBundle	*bundle;
	
    (void)time(&now);
    srandom((int)now^(0xffffff));
	if (!initted) {
	for(i=0; i < NIMAGES; i++) face[i] = nil;
	bundle = [NXBundle bundleForClass:[EightBawl class]];
	if ([bundle getPath:buf forResource:"Base8" ofType:"eps"] )
		base8 = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"Big8" ofType:"eps"] )
		big8 = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"small8" ofType:"tiff"] )
		face[0] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"ask_again" ofType:"tiff"] )
		face[1] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"as_i_see_it" ofType:"tiff"] )
		face[2] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"better_not" ofType:"tiff"] )
		face[3] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"certain" ofType:"tiff"] )
		face[4] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"cannot_predict" ofType:"tiff"] )
		face[5] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"concentrate" ofType:"tiff"] )
		face[6] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"decidedly" ofType:"tiff"] )
		face[7] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"may_rely" ofType:"tiff"] )
		face[8] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"outlook_good" ofType:"tiff"] )
		face[9] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"definitely" ofType:"tiff"] )
		face[10] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"outlook_not" ofType:"tiff"] )
		face[11] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"reply_hazy" ofType:"tiff"] )
		face[12] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"dont_count" ofType:"tiff"] )
		face[13] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"reply_no" ofType:"tiff"] )
		face[14] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"signs_point" ofType:"tiff"] )
		face[15] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"doubtful" ofType:"tiff"] )
		face[16] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"sources_say" ofType:"tiff"] )
		face[17] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"without_doubt" ofType:"tiff"] )
		face[18] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"most_likely" ofType:"tiff"] )
		face[19] = [[NXImage alloc] initFromFile:buf];
	if ([bundle getPath:buf forResource:"yes" ofType:"tiff"] )
		face[20] = [[NXImage alloc] initFromFile:buf];
	initted = YES;
	}
	[theApp   registerAnnotation: [EightBawl class] 
							name: "EightBawl"
					RTFDirective: "EightBawl"
					   menuLabel: "Fun Stuff/Consult 8Bawl..."
						 menuKey: '\0'
						menuIcon: (NXImage *) face[0]];
	return self;
}

- init
{
	cimage = [[NXImage alloc] initSize:&smallRectSize];
    [cimage setUnique:YES];	// this image must stay opaque!
    [cimage setBackgroundColor:NX_COLORWHITE];
    [cimage useCacheWithDepth:NX_DefaultDepth];
	return self;
}

- free
{
	[[NXApp inspector] invalidate];
	return [super free];
}

- initFromPboard:thePB inDoc:theDoc linked:(BOOL) linked {return [self init];}

// drawing loops -- trackMouse
- anim:controlView
{
	
	[controlView lockFocus];
	PSgsave();
	if (animStep == 5) {
		NXPoint point;
		
		PSsetgray([controlView backgroundGray]);
		NXRectFill(&savedFrame);
		point = savedFrame.origin;
		point.y += savedFrame.size.height;
		[big8 composite:NX_SOVER toPoint:&point];
	} else {
		[cimage dissolve:((++animStep) * .2) toPoint:&savedPoint];
		[self perform:@selector(anim:) with:controlView afterDelay:1000 cancelPrevious:NO];
	}
	PSgrestore(); 
	[controlView unlockFocus];
	DPSFlush();
	NXPing();
	return self;
}

- (BOOL)	trackMouse:(NXEvent *)event
			inRect:(const NXRect *)cellFrame
			ofView:controlView	
{
    const NXPoint zero={ 0.0, 0.0 };
    NXRect cr;
	NXPoint	point;
	int k;

	[[NXApp inspector] inspect:[EBI new]];	
    PSgsave();
    PSobscurecursor();
    PSsetwaitcursorenabled(NO);	// cheating!
	if (highlighted) PSsetgray(NX_LTGRAY);
	else PSsetgray([controlView backgroundGray]);
	NXRectFill(cellFrame);
	PSgrestore();
	point = cellFrame->origin;
    point.y += cellFrame->size.height;
	[base8 composite:NX_SOVER toPoint:&point];
	point.x += smallRectOrigin.x;
	k = (int)(random()&0x7fffffff)%(NIMAGES-1) + 1;
	if ((k-1)%3 == 0) point.y -= smallRectUpOrigin.y;
	else point.y -= smallRectOrigin.y;
//	dissolve base8 up to face[k]	
	[cimage lockFocus];
	cr.size = smallRectSize;
    cr.origin=((k-1)%3 == 0) ? smallRectUpOrigin : smallRectOrigin;
	[base8 composite:NX_SOVER fromRect:&cr toPoint:&zero];
	[face[k] composite:NX_SOVER toPoint:&zero];
	[cimage unlockFocus];
	
	animStep = 0;
	savedPoint = point;
	savedFrame = *cellFrame;
	[self perform:@selector(anim:) with:controlView afterDelay:1000 cancelPrevious:NO];
	
//	for (dpt = 0.1; dpt < 1.0; dpt += .1){
//		[cimage dissolve:dpt toPoint:&point];
//		DPSFlush();
//		[[controlView window] flushWindow];
//		NXPing();
//	}
//	dissolve face[k] down to big8
	PSgsave();
//	PSsetgray([controlView backgroundGray]);
//	NXRectFill(cellFrame);
//	point = cellFrame->origin;
//  point.y += cellFrame->size.height;
//	[big8 composite:NX_SOVER toPoint:&point]; 
//	[cimage composite:NX_SOVER toPoint:&point];

	PSgrestore();
    PSsetwaitcursorenabled(YES);
	return YES;
}
// default drawSelf
- drawSelf:(const NXRect *)cellFrame inView:view
{
	NXPoint	point;
	
    PSgsave();
	if (highlighted) PSsetgray(NX_LTGRAY);
	else PSsetgray([view backgroundGray]);
	NXRectFill(cellFrame);
	
    point = cellFrame->origin;
    point.y += cellFrame->size.height;
	[big8 composite:NX_SOVER toPoint:&point];
    PSgrestore();
    return self;
}

- calcCellSize:(NXSize *)theSize 
	{theSize->width = theSize->height = 288.0; return self;}
- highlight:(const NXRect *)rect inView:view lit:(BOOL)flag
	{highlighted = !highlighted; NXHighlightRect(rect);return self;}
- readRichText:(NXStream *)stream forView:view 
	{return self;}
- writeRichText:(NXStream *)stream forView:view
	{return self;}
@end